perf: reduce allocations in beatmap conversion, playable bounds, and HUD components - #345
Merged
winnerspiros merged 7 commits intoMay 21, 2026
Merged
Conversation
…ng when OverlayActivationMode is wrong Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/b0503980-c181-4806-a9b6-a2b891be69df Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
- OsuFramedReplayInputHandler.IsImportant: frame.Actions.Any() → frame.Actions.Count > 0 (called every replay frame; removes enumerator alloc) - SpeedEvaluator.EvaluateDifficultyOf: mods.OfType<OsuModAutopilot>().Any() → inline for-loop with early break (called per note in difficulty calc) - RhythmEvaluator.EvaluateDifficultyOf: replaced double-scan pattern (FirstOrDefault + IndexOf, two O(n) passes) with a single indexed for-loop that finds and mutates the entry in one pass - OsuDifficultyCalculator.CreateDifficultyAttributes: replaced three separate beatmap.HitObjects.Count(h => h is T) calls (three full enumerations) with a single switch-based loop; also replaced four skills.OfType<T>().Single/SingleOrDefault() calls with a single typed loop - OsuDifficultyCalculator.CreateSkills: mods.Any(h => h is OsuModFlashlight) → inline for-loop with early break - OsuAutoGenerator.addHitObjectClickFrames: previousActions.Any() → .Count > 0; frame.Actions.SequenceEqual(previousActions) → new static ActionsEqual helper (avoids IEnumerable allocation on every frame) Removed now-unused 'using System.Linq' from all changed files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…erhead - AndroidMouseHandler/StylusHandler/KeyboardHandler: add volatile bool cachedEnabled field (mirror of Enabled.Value via BindValueChanged), matching the existing cachedSensitivity/cachedPressureThreshold/ TreatAsTouch pattern. The OS dispatch thread now reads a direct volatile field instead of traversing the Bindable<bool> property chain on every MotionEvent/KeyEvent. The volatile write-then-read guarantees the same cross-thread visibility that a BindValueChanged-to-Update-thread would provide for the enable/disable path. - OsuGameAndroid: add adpfDrawThread/adpfUpdateThread/adpfInputThread GameThread? fields, assigned once when each ADPF hint session is created (on the respective game thread). The three per-frame FrameCompleted callbacks (onDrawFrameCompleted, onUpdateFrameCompleted, onInputFrameCompleted) now read adpf*Thread?.Clock.ElapsedFrameTime instead of Host?.DrawThread?.Clock.ElapsedFrameTime, removing two levels of nullable chain traversal per call. At 120 Hz × 3 threads these callbacks fire ~360 times/second, so eliminating the Host and *Thread property accesses is a measurable reduction in per-frame bookkeeping cost. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…HUD components - BeatmapConverter: replace OrderBy().ToList() with in-place List<T>.Sort() to avoid creating an intermediate IOrderedEnumerable and a second list. - IBeatmap.CalculatePlayableBounds: collapse three separate LINQ enumerations (Any, Max, First) into a single foreach loop. Reduces from O(3n) to O(n) and eliminates two LINQ iterator allocations on every call site. - PausableSkinnableSound.Length: previously evaluated DrawableSamples twice (once for Any(), once for Max()), creating two LINQ chains. Replaced with a single foreach that accumulates the maximum sample length. - JudgementCounter, JudgementCounterDisplay, ArgonJudgementCounter, ArgonJudgementCounterDisplay: replaced Types.First() with direct Types[0] array indexing and removed the now-unused 'using System.Linq' imports. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
winnerspiros
May 21, 2026 07:23
View session
winnerspiros
approved these changes
May 21, 2026
… in ranked rooms) Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/27570109-9bbd-46a9-bb06-b8e5b4034215 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
winnerspiros
approved these changes
May 21, 2026
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/c05408ff-2261-4192-be17-427dbac05881 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
winnerspiros
approved these changes
May 21, 2026
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/53e9d70f-a74f-443c-9861-5f785a91df94 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
winnerspiros
approved these changes
May 21, 2026
Copilot stopped work on behalf of
winnerspiros due to an error
May 21, 2026 12:45
winnerspiros
approved these changes
May 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.